#!/usr/bin/python3
# ******************************************************************************
# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
# licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#     http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# ******************************************************************************/
import os.path
import stat
import subprocess

from exception import ConfigNotFoundError, PathNotExistError, PathEmptyError
from logger import logger

CURRENT_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)))


class PathApply:
    """
    Patch verification class
    """

    def __init__(self, rpm_name, patch_path, source_path, branch_rpm):
        self.rpm_name = rpm_name
        self.patch_path = patch_path
        self.source_path = source_path
        self.branch_rpm = branch_rpm

    def packing_source(self):
        """
        Package verification implementation class
        :return: None
        """
        logger.info(
            f'Start to apply patch in "{self.patch_path}" of package "{self.rpm_name}", branch is "{self.branch_rpm}"')
        self._validate_path()
        self._change_shell_right()
        run_shell = os.path.join(CURRENT_PATH, 'run.sh')
        try:
            output = subprocess.check_output(
                [run_shell, self.rpm_name, self.branch_rpm, self.patch_path, self.source_path],
                stderr=subprocess.STDOUT,
                shell=False)
            apply_result = output.decode('utf-8')
            logger.info(f'Patch verification process:\n{apply_result}')
            logger.info(f'Apply patch successfully, log is {self.source_path}/{self.rpm_name}/result.log')
        except subprocess.CalledProcessError as e:
            logger.info(f'Patch verification process:\n{e.output.decode("utf-8")}')
            logger.error(f'Apply patch failed, log is {self.source_path}/{self.rpm_name}/result.log')

    def _validate_path(self):
        """
        Verify the legitimacy of each path
        :return: None
        :raise: ConfigNotFoundError PathNotExistError PathEmptyError
        """
        if not self.patch_path or not self.source_path:
            raise ConfigNotFoundError('Patch path (PATCH_SAVE_PATH) or source path (SOURCE_CODE_PATH) does not exist')

        if not os.path.isdir(self.source_path):
            logger.warning(f'The source package download path: {self.source_path} does not exist, it will be created')
            try:
                os.makedirs(self.source_path)
            except PermissionError:
                logger.error(f'Insufficient permissions to create a path')
                raise PathNotExistError(self.source_path)
        if not os.path.isdir(self.patch_path):
            raise PathNotExistError(self.patch_path)

        if not os.listdir(self.patch_path):
            raise PathEmptyError(self.patch_path)

    @staticmethod
    def _change_shell_right():
        """
        Give shell script execution permissions
        :return: None
        """
        for file in os.listdir(CURRENT_PATH):
            if str(file).endswith('.sh'):
                os.chmod(os.path.join(CURRENT_PATH, file), 0o0755)
